home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 1 / LIGHT-ROM 1 (Amiga Library Services)(1994).iso / ffdisks / d927.lha / Telnet / src / sys_bsd.c < prev    next >
C/C++ Source or Header  |  1993-10-07  |  13KB  |  643 lines

  1. /*
  2.  * Copyright (c) 1988, 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted provided
  6.  * that: (1) source distributions retain this entire copyright notice and
  7.  * comment, and (2) distributions including binaries display the following
  8.  * acknowledgement:  ``This product includes software developed by the
  9.  * University of California, Berkeley and its contributors'' in the
  10.  * documentation or other materials provided with the distribution and in
  11.  * all advertising materials mentioning features or use of this software.
  12.  * Neither the name of the University nor the names of its contributors may
  13.  * be used to endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  16.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)sys_bsd.c    5.1 (Berkeley) 9/14/90";
  22. #endif /* not lint */
  23.  
  24. /*
  25.  * The following routines try to encapsulate what is system dependent
  26.  * (at least between 4.x and dos) which is used in telnet.c.
  27.  */
  28.  
  29.  
  30. #include <fcntl.h>
  31. #include <sys/types.h>
  32. #include <sys/time.h>
  33. #include <string.h>
  34. #include <sys/socket.h>
  35. #ifdef AMI_TCP
  36. #include <bsdsocket.h>
  37. #else
  38. #include <ss/socket.h>
  39. #endif
  40. #include <signal.h>
  41. #include <errno.h>
  42. #include <arpa/telnet.h>
  43. #ifdef __SASC
  44. #include <ios1.h>
  45. #endif
  46. #include "ring.h"
  47.  
  48. #include "fdset.h"
  49.  
  50. #include "defines.h"
  51. #include "externs.h"
  52. #include "types.h"
  53.  
  54. #define    SIG_FUNC_RET    int
  55.  
  56. int
  57.     tout,            /* Output file descriptor */
  58.     tin,            /* Input file descriptor */
  59.     net;
  60.  
  61. #ifndef AMI_TCP
  62. struct    tchars otc = { 0 }, ntc = { 0 };
  63. struct    sgttyb ottyb = { 0 }, nttyb = { 0 };
  64. #endif
  65. int    olmode = 0;
  66. # define cfgetispeed(ptr)    (ptr)->sg_ispeed
  67. # define cfgetospeed(ptr)    (ptr)->sg_ospeed
  68. # define old_tc ottyb
  69.  
  70. static fd_set ibits, obits, xbits;
  71.  
  72. //void (*signal())()
  73. //{    return;
  74. //}
  75.  
  76. init_sys()
  77. {
  78.     tout = fileno(stdout);
  79.     tin = fileno(stdin);
  80.     FD_ZERO(&ibits);
  81.     FD_ZERO(&obits);
  82.     FD_ZERO(&xbits);
  83.  
  84.     errno = 0;
  85. }
  86.  
  87.  
  88. TerminalWrite(buf, n)
  89. char    *buf;
  90. int    n;
  91. {
  92.     return write(tout, buf, n);
  93. }
  94.  
  95. TerminalRead(buf, n)
  96. char    *buf;
  97. int    n;
  98. {
  99.     return read(tin, buf, n);
  100. }
  101.  
  102. /*
  103.  *
  104.  */
  105.  
  106. int
  107. TerminalAutoFlush()
  108. {
  109.     return 1;
  110. }
  111.  
  112.  
  113. /*
  114.  * Flush output to the terminal
  115.  */
  116.  
  117. void
  118. TerminalFlushOutput()
  119. {
  120.     fflush(stdout);
  121. }
  122.  
  123. void
  124. TerminalSaveState()
  125. {
  126. return;
  127. }
  128.  
  129. cc_t *
  130. tcval(func)
  131. register int func;
  132. {
  133.     switch(func) {
  134.     case SLC_SYNCH:
  135.     case SLC_BRK:
  136.     case SLC_EOR:
  137.     default:
  138.     return((cc_t *)0);
  139.     }
  140. }
  141.  
  142. void
  143. TerminalDefaultChars()
  144. {
  145. return;
  146. }
  147.  
  148. #ifdef notdef
  149. void
  150. TerminalRestoreState()
  151. {
  152. }
  153. #endif
  154.  
  155. /*
  156.  * TerminalNewMode - set up terminal to a specific mode.
  157.  *    MODE_ECHO: do local terminal echo
  158.  *    MODE_FLOW: do local flow control
  159.  *    MODE_TRAPSIG: do local mapping to TELNET IAC sequences
  160.  *    MODE_EDIT: do local line editing
  161.  *
  162.  *    Command mode:
  163.  *        MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
  164.  *        local echo
  165.  *        local editing
  166.  *        local xon/xoff
  167.  *        local signal mapping
  168.  *
  169.  *    Linemode:
  170.  *        local/no editing
  171.  *    Both Linemode and Single Character mode:
  172.  *        local/remote echo
  173.  *        local/no xon/xoff
  174.  *        local/no signal mapping
  175.  */
  176.  
  177.  
  178. void
  179. TerminalNewMode(f)
  180. register int f;
  181. {
  182.     static int prevmode = 0;
  183. #ifndef    USE_TERMIO
  184. #ifdef __SASC
  185.      int    ami_cbreak = 0;
  186. #else
  187.     struct sgttyb sb;
  188. #endif
  189. #endif
  190.     int lmode;
  191.     int onoff;
  192.     int old;
  193.  
  194.     globalmode = f&~MODE_FORCE;
  195.     if (prevmode == f)
  196.     return;
  197.  
  198.     /*
  199.      * Write any outstanding data before switching modes
  200.      * ttyflush() returns 0 only when there is no more data
  201.      * left to write out, it returns -1 if it couldn't do
  202.      * anything at all, otherwise it returns 1 + the number
  203.      * of characters left to write.
  204. #ifndef    USE_TERMIO
  205.      * We would really like ask the kernel to wait for the output
  206.      * to drain, like we can do with the TCSADRAIN, but we don't have
  207.      * that option.  The only ioctl that waits for the output to
  208.      * drain, TIOCSETP, also flushes the input queue, which is NOT
  209.      * what we want (TIOCSETP is like TCSADFLUSH).
  210. #endif
  211.      */
  212.     old = ttyflush(SYNCHing|flushout);
  213.     if (old < 0 || old > 1) {
  214.     do {
  215.         /*
  216.          * Wait for data to drain, then flush again.
  217.          */
  218.         old = ttyflush(SYNCHing|flushout);
  219.     } while (old < 0 || old > 1);
  220.     }
  221.  
  222.     old = prevmode;
  223.     prevmode = f&~MODE_FORCE;
  224.     lmode = olmode;
  225.  
  226.     if (f&MODE_ECHO) {
  227. #ifndef __SASC
  228.     sb.sg_flags |= ECHO;
  229. #endif
  230.     } else {
  231. #ifndef __SASC
  232.     sb.sg_flags &= ~ECHO;
  233. #endif
  234.     }
  235.  
  236.     if ((f&MODE_FLOW) == 0) {
  237.     }
  238.  
  239.     if ((f&MODE_TRAPSIG) == 0) {
  240.     localchars = 0;
  241.     } else {
  242.     localchars = 1;
  243.     }
  244.  
  245.     if (f&MODE_EDIT) {
  246. #ifdef __SASC
  247.     ami_cbreak = 0;
  248. #else
  249.     sb.sg_flags &= ~CBREAK;
  250.     sb.sg_flags &= ~RAW;
  251.     sb.sg_flags |= CRMOD;
  252. #endif
  253.     } else {
  254. #ifdef __SASC
  255.     ami_cbreak = 1;
  256. #else
  257.     sb.sg_flags |= CBREAK;
  258.     sb.sg_flags |= RAW;
  259.     if (f&MODE_ECHO)
  260.         sb.sg_flags |= CRMOD;
  261.     else
  262.         sb.sg_flags &= ~CRMOD;
  263. #endif
  264.     }
  265.  
  266.     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
  267.     }
  268.  
  269.     if (f&MODE_SOFT_TAB) {
  270. #ifndef __SASC
  271.     sb.sg_flags |= XTABS;
  272. #endif
  273.     } else {
  274. #ifndef __SASC
  275.     sb.sg_flags &= ~XTABS;
  276. #endif
  277.     }
  278.  
  279.     if (f&MODE_LIT_ECHO) {
  280.     } else {
  281.     }
  282.  
  283.     if (f == -1) {
  284.     onoff = 0;
  285.     } else {
  286.     onoff = 1;
  287.     }
  288.  
  289.     if (f != -1) {
  290.     /*
  291.      * We don't want to process ^Y here.  It's just another
  292.      * character that we'll pass on to the back end.  It has
  293.      * to process it because it will be processed when the
  294.      * user attempts to read it, not when we send it.
  295.      */
  296.     } else {
  297.     lmode = olmode;
  298.     }
  299. #ifdef __SASC
  300.     SetMode(chkufb(0)->ufbfh,ami_cbreak);
  301. #else
  302.     SetMode(_devtab[0].fd,(sb.sg_flags & CBREAK) ? 1L : 0L);
  303. #endif
  304.  
  305.     ioctl(tin, FIONBIO, (char *)&onoff);
  306.     ioctl(tout, FIONBIO, (char *)&onoff);
  307. }
  308.  
  309.  
  310. int
  311. TerminalWindowSize(rows, cols)
  312. long *rows, *cols;
  313. {
  314.     return 0;
  315. }
  316.  
  317. int
  318. NetClose(fd)
  319. int    fd;
  320. {
  321. #ifdef AMI_TCP
  322.      return CloseSocket(fd);
  323. #else
  324.     return s_close(fd);
  325. #endif
  326. }
  327.  
  328.  
  329. void
  330. NetNonblockingIO(fd, onoff)
  331. int
  332.     fd,
  333.     onoff;
  334. {
  335.     ioctl(fd, FIONBIO, (char *)&onoff);
  336. }
  337.  
  338. /*
  339.  * Various signal handling routines.
  340.  */
  341.  
  342. /* ARGSUSED */
  343. static SIG_FUNC_RET
  344. deadpeer(sig)
  345. int sig;
  346. {
  347.     setcommandmode();
  348.     longjmp(peerdied, -1);
  349. }
  350.  
  351. /* ARGSUSED */
  352. static SIG_FUNC_RET
  353. intr(sig)
  354. int sig;
  355. {
  356.     if (localchars) {
  357.     intp();
  358.     return;
  359.     }
  360.     setcommandmode();
  361.     longjmp(toplevel, -1);
  362. }
  363.  
  364. /* ARGSUSED */
  365. static SIG_FUNC_RET
  366. intr2(sig)
  367. int sig;
  368. {
  369.     if (localchars) {
  370.         sendabort();
  371.     return;
  372.     }
  373. }
  374.  
  375. #ifdef    SIGTSTP
  376. /* ARGSUSED */
  377. static SIG_FUNC_RET
  378. susp(sig)
  379. int sig;
  380. {
  381.     if (localchars)
  382.     sendsusp();
  383. }
  384. #endif
  385.  
  386. #ifdef    SIGWINCH
  387. /* ARGSUSED */
  388. static SIG_FUNC_RET
  389. sendwin(sig)
  390. int sig;
  391. {
  392.     if (connected) {
  393.     sendnaws();
  394.     }
  395. }
  396. #endif
  397.  
  398. #ifdef    SIGINFO
  399. /* ARGSUSED */
  400. static SIG_FUNC_RET
  401. ayt(sig)
  402. int sig;
  403. {
  404.     if (connected)
  405.     sendayt();
  406.     else
  407.     ayt_status();
  408. }
  409. #endif
  410.  
  411. void
  412. sys_telnet_init()
  413. {
  414.     setconnmode(0);
  415.  
  416.     NetNonblockingIO(net, 1);
  417.  
  418. #if    defined(SO_OOBINLINE)
  419.    {    int one=1;
  420. #ifdef AMI_TCP
  421.     if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one,sizeof(one)) == -1) 
  422. #else
  423.     if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, &one,sizeof(one)) == -1) 
  424. #endif
  425.     {
  426.         perror("SetSockOpt");
  427.     }
  428.    }
  429. #endif    /* defined(SO_OOBINLINE) */
  430. }
  431.  
  432. /*
  433.  * Process rings -
  434.  *
  435.  *    This routine tries to fill up/empty our various rings.
  436.  *
  437.  *    The parameter specifies whether this is a poll operation,
  438.  *    or a block-until-something-happens operation.
  439.  *
  440.  *    The return value is 1 if something happened, 0 if not.
  441.  */
  442.  
  443. int
  444. process_rings(netin, netout, netex, ttyin, ttyout, poll)
  445. int poll;        /* If 0, then block until something to do */
  446. {
  447.     register int c;
  448.         /* One wants to be a bit careful about setting returnValue
  449.          * to one, since a one implies we did some useful work,
  450.          * and therefore probably won't be called to block next
  451.          * time (TN3270 mode only).
  452.          */
  453.     int returnValue = 0;
  454.     static struct timeval TimeValue = { 0 };
  455.     static struct timeval Quickie = {0L,20000L};
  456.     extern long bytesin;
  457.     if (netout) {
  458.     FD_SET(net, &obits);
  459.     } 
  460.     if (netin) {
  461.     FD_SET(net, &ibits);
  462.     }
  463.     if (netex) {
  464.     FD_SET(net, &xbits);
  465.     }
  466.     if ((c = select(16, &ibits, &obits, &xbits,
  467.             (poll == 0)? (struct timeval *)&Quickie : &TimeValue)) < 0) {
  468.     if (c == -1) {
  469.             /*
  470.              * we can get EINTR if we are in line mode,
  471.              * and the user does an escape (TSTP), or
  472.              * some other signal generator.
  473.              */
  474.         if (errno == EINTR) {
  475.         return 0;
  476.         }
  477.             /* I don't like this, does it ever happen? */
  478.         printf("sleep(5) from telnet, after select\r\n");
  479.         sleep(5);
  480.     }
  481.     return 0;
  482.     }
  483.  
  484.     /*
  485.      * Any urgent data?
  486.      */
  487.     if (FD_ISSET(net, &xbits)) {
  488.     FD_CLR(net, &xbits);
  489.     SYNCHing = 1;
  490.     (void) ttyflush(1);    /* flush already enqueued data */
  491.     }
  492.  
  493.     /*
  494.      * Something to read from the network...
  495.      */
  496.     if (FD_ISSET(net, &ibits)) {
  497.     int canread;
  498.  
  499.     FD_CLR(net, &ibits);
  500.     canread = ring_empty_consecutive(&netiring);
  501. #if    !defined(SO_OOBINLINE)
  502.         /*
  503.          * In 4.2 (and some early 4.3) systems, the
  504.          * OOB indication and data handling in the kernel
  505.          * is such that if two separate TCP Urgent requests
  506.          * come in, one byte of TCP data will be overlaid.
  507.          * This is fatal for Telnet, but we try to live
  508.          * with it.
  509.          *
  510.          * In addition, in 4.2 (and...), a special protocol
  511.          * is needed to pick up the TCP Urgent data in
  512.          * the correct sequence.
  513.          *
  514.          * What we do is:  if we think we are in urgent
  515.          * mode, we look to see if we are "at the mark".
  516.          * If we are, we do an OOB receive.  If we run
  517.          * this twice, we will do the OOB receive twice,
  518.          * but the second will fail, since the second
  519.          * time we were "at the mark", but there wasn't
  520.          * any data there (the kernel doesn't reset
  521.          * "at the mark" until we do a normal read).
  522.          * Once we've read the OOB data, we go ahead
  523.          * and do normal reads.
  524.          *
  525.          * There is also another problem, which is that
  526.          * since the OOB byte we read doesn't put us
  527.          * out of OOB state, and since that byte is most
  528.          * likely the TELNET DM (data mark), we would
  529.          * stay in the TELNET SYNCH (SYNCHing) state.
  530.          * So, clocks to the rescue.  If we've "just"
  531.          * received a DM, then we test for the
  532.          * presence of OOB data when the receive OOB
  533.          * fails (and AFTER we did the normal mode read
  534.          * to clear "at the mark").
  535.          */
  536.     if (SYNCHing) {
  537.         int atmark;
  538.         static int bogus_oob = 0, first = 1;
  539.  
  540.         s_ioctl(net, SIOCATMARK, (char *)&atmark);
  541.         if (atmark) {
  542.         c = recv(net, netiring.supply, canread, MSG_OOB);
  543.         if ((c == -1) && (errno == EINVAL)) {
  544.             c = recv(net, netiring.supply, canread, 0);
  545.             if (clocks.didnetreceive < clocks.gotDM) {
  546.             SYNCHing = stilloob(net);
  547.             }
  548.         } else if (first && c > 0) {
  549.             /*
  550.              * Bogosity check.  Systems based on 4.2BSD
  551.              * do not return an error if you do a second
  552.              * recv(MSG_OOB).  So, we do one.  If it
  553.              * succeeds and returns exactly the same
  554.              * data, then assume that we are running
  555.              * on a broken system and set the bogus_oob
  556.              * flag.  (If the data was different, then
  557.              * we probably got some valid new data, so
  558.              * increment the count...)
  559.              */
  560.             int i;
  561.             i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
  562.             if (i == c &&
  563.               bcmp(netiring.supply, netiring.supply + c, i) == 0) {
  564.             bogus_oob = 1;
  565.             first = 0;
  566.             } else if (i < 0) {
  567.             bogus_oob = 0;
  568.             first = 0;
  569.             } else
  570.             c += i;
  571.         }
  572.         if (bogus_oob && c > 0) {
  573.             int i;
  574.             /*
  575.              * Bogosity.  We have to do the read
  576.              * to clear the atmark to get out of
  577.              * an infinate loop.
  578.              */
  579.             i = read(net, netiring.supply + c, canread - c);
  580.             if (i > 0)
  581.             c += i;
  582.         }
  583.         } else {
  584.         c = recv(net, netiring.supply, canread, 0);
  585.         }
  586.     } else {
  587.         c = recv(net, netiring.supply, canread, 0);
  588.     }
  589.     settimer(didnetreceive);
  590. #else    /* !defined(SO_OOBINLINE) */
  591.     c = recv(net, netiring.supply, canread, 0);
  592. #endif    /* !defined(SO_OOBINLINE) */
  593.     if (c < 0 && errno == EWOULDBLOCK) {
  594.         c = 0;
  595.     } else if (c <= 0) {
  596.         return -1;
  597.     }
  598.     if (netdata) {
  599.         Dump('<', netiring.supply, c);
  600.     }
  601.     if (c)
  602.         bytesin+=c;
  603.         ring_supplied(&netiring, c);
  604.     returnValue = 1;
  605.     }
  606.  
  607.     /*
  608.      * Something to read from the tty...
  609.      */
  610. #ifdef __SASC
  611.     if (WaitForChar(chkufb(0)->ufbfh,Quickie.tv_usec)) {
  612. #else
  613.     if (WaitForChar(_devtab[0].fd,Quickie.tv_usec)) {
  614. #endif
  615. //    FD_CLR(tin, &ibits);
  616.     c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
  617.     if (c < 0 && errno == EWOULDBLOCK) {
  618.         c = 0;
  619.     } else {
  620.         /* EOF detection for line mode!!!! */
  621.         if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
  622.             /* must be an EOF... */
  623. #ifndef __SASC
  624.         *ttyiring.supply = termEofChar;
  625. #endif
  626.         c = 1;
  627.         }
  628.         if (c <= 0) {
  629.         return -1;
  630.         }
  631.         ring_supplied(&ttyiring, c);
  632.     }
  633.     returnValue = 1;        /* did something useful */
  634.     }
  635.  
  636.     if (FD_ISSET(net, &obits)) {
  637.     FD_CLR(net, &obits);
  638.     returnValue |= netflush();
  639.     }
  640.     returnValue |= (ttyflush(SYNCHing|flushout) > 0);
  641.     return returnValue;
  642. }
  643.